package redis

import (
	"context"
	"fmt"
	"gf-xb-api/internal/config/apollo"
	"gf-xb-api/internal/consts"

	gfRedis "github.com/gogf/gf/contrib/nosql/redis/v2"

	"github.com/gogf/gf/v2/container/gvar"
	"github.com/gogf/gf/v2/database/gredis"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gctx"
)

var (
	ctx   = gctx.New()
	group = "cache"
)

// MyRedis ... description
type MyRedis struct {
	*gfRedis.Redis
}

// Do implements and overwrites the underlying function Do from Adapter.
func (r *MyRedis) Do(ctx context.Context, command string, args ...interface{}) (*gvar.Var, error) {
	fmt.Println("MyRedis Do:", command, args)
	return r.Redis.Do(ctx, command, args...)
}

func init() {
	host := apollo.GetStringValue(consts.RedisConfig_Host)
	port := apollo.GetIntValue(consts.RedisConfig_Port)
	pass := apollo.GetStringValue(consts.RedisConfig_Password)
	db := apollo.GetIntValue(consts.RedisConfig_DefaultDatabase)

	address := fmt.Sprintf("%s:%d", host, *port)

	config := gredis.Config{
		Address: address,
		Db:      *db,
		Pass:    pass,
	}

	gredis.RegisterAdapterFunc(func(config *gredis.Config) gredis.Adapter {
		r := &MyRedis{gfRedis.New(config)}
		r.AdapterOperation = r // This is necessary.
		return r
	})
	gredis.SetConfig(&config, group)
}

// Expire ... 在seconds秒后过期
func Expire(key string, seconds int64) error {
	_, err := g.Redis(group).Expire(ctx, key, seconds)
	if err != nil {
		g.Log().Fatal(ctx, err)
	}

	return err
}

// Del ... 删除键
func Del(keys ...string) error {
	_, err := g.Redis(group).Del(ctx, keys...)
	if err != nil {
		g.Log().Fatal(ctx, err)
	}

	return err
}

// SetStringValue ... 设置字符串Key值
func SetStringValue(key, val string) error {
	_, err := g.Redis(group).Set(ctx, key, val)
	if err != nil {
		g.Log().Fatal(ctx, err)
	}

	return err
}

// SetStringValueEx ... 设置字符串Key值和过期时间
func SetStringValueEx(key, val string, ttlInSeconds int64) error {
	return g.Redis(group).SetEX(ctx, key, val, ttlInSeconds)
}

// GetStringValue ... 获得字符串Key值
func GetStringValue(key string) *string {
	val, err := g.Redis(group).Get(ctx, key)
	if err != nil {
		g.Log().Fatal(ctx, err)
		return nil
	}

	str := val.String()
	return &str
}

// HSet ... hash set
func HSet(key string, fields map[string]interface{}) error {
	_, err := g.Redis(group).HSet(ctx, key, fields)
	if err != nil {
		g.Log().Fatal(ctx, err)
	}

	return err
}
